package com.android.WiFiQualityMeasurement;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.TelephonyManager;
import android.util.Log;



public class WiFiQualityMeasurementService extends Service implements LocationListener{

	private String				mStringFilePath;					// ファイル関係
	private File 				mFile;								// ファイル関係
	private FileOutputStream 	mFos;								// ファイル関係
	private TelephonyManager 	mTelephonyManager;					// Telephonyマネージャー
	private String 				mStringLineType;					// 捕捉回線種別
	private WifiManager 		mWifiManager;						// Wifiマネージャー
	private WifiInfo 			mWifiInfo;							// Wifiインフォ
	private ConnectivityManager	mConManager;						// コネクティビティマネージャ
	private NetworkInfo 		mNetInfo;							// ネットワークインフォ
	private String 				mStringThroughput;					// スループット値
	private String 				mStringElectricFieldStrength;		// 電界強度
	private Calendar 			mCalendar;							// カレンダークラス
	private String 				mStringDayTime;						// 年月日時分秒ミリ秒
	private String				mStringDayTime2;					// 年月日時分秒
	private LocationManager		mLocationManager;					// ロケーションマネージャ
	private String				mStringLatitude;					// 緯度
	private String				mStringLongitude;					// 経度
	private String				mStringBssid;						// BSSID
	private String				mStringMacAddress;					// MacAddress
	private String				mStringModel;						// 端末種別
	private String				mStringSsid;						// SSID
	private String				mStringCareerName;					// キャリア名

	private int 				mInterval = 50;						// インターバル5秒
	private int 				mTickCount;							// タイマーカウンタ
	private Timer 				mTimer;								// タイマを定義

	/* 2010.11.13 SANO DEL START */
	//private Intent				mIntent;							// アクティビティへのデータ渡し
	/* 2010.11.13 SANO DEL END */

    public static final String ACTION = "WiFiQualityMeasurement Service";

	@Override
	public void onCreate() {
		super.onCreate();

		// インスタンス初期化
		mCalendar = Calendar.getInstance();
		mStringFilePath = Environment.getExternalStorageDirectory() + "/" +
						Integer.toString(mCalendar.get(Calendar.YEAR)) +
				    	Integer.toString(mCalendar.get(Calendar.MONTH)) +
				    	Integer.toString(mCalendar.get(Calendar.DAY_OF_MONTH)) +
				    	Integer.toString(mCalendar.get(Calendar.HOUR_OF_DAY)) +
				    	Integer.toString(mCalendar.get(Calendar.MINUTE)) +
				    	Integer.toString(mCalendar.get(Calendar.SECOND)) +
				    	Integer.toString(mCalendar.get(Calendar.MILLISECOND)) +
						".txt";

		Log.d("WiFiQualityMeasurementService","FilePath = " +mStringFilePath );

		mTimer = null;
		mStringLatitude = "";	// 緯度
		mStringLongitude = "";	// 経度
		mFile = new File(mStringFilePath);
		if(mFile != null)
		{
			mFile.getParentFile().mkdir();
		}

		mTimer = new Timer(true);
        final android.os.Handler handler = new android.os.Handler();
        if(mTimer != null && handler != null)
        {
	        mTimer.schedule(
	        	new TimerTask() {
	        		@Override
	        		public void run() {
	        			handler.post( new Runnable(){
	        				public void run(){
	        					// タイマー毎の描画処理
	        					mTickCount++;

	        					if(mTickCount >= mInterval)
	        					{
	        						// インターバルごとに、Wifi情報を取得する
	        						getState();

	        						// インターバルごとに、ログをサーバにアップロード
	        						//saveState();
	        						sendLog();

	        						/* 2010.11.13 SANO DEL START */
	        						//mIntent = new Intent(ACTION);
	        						//if(mIntent != null)
	        						//{
	        						//	mIntent.putExtra("LINETYPE", mStringLineType);
	        						//	mIntent.putExtra("CAREERNAME", mStringCareerName);
									//
	        						//	mIntent.putExtra("SSID", mStringSsid);
	        						//	mIntent.putExtra("BSSID", mStringBssid);
	        						//	mIntent.putExtra("THROUGHPUT", mStringThroughput);
	        						//	mIntent.putExtra("ELECTRICFIELDSTRENGTH", mStringElectricFieldStrength);
	        						//
	        						//	mIntent.putExtra("MACADDRESS", mStringMacAddress);
	        						//	mIntent.putExtra("MODEL", mStringModel);
	        						//
	        						//	mIntent.putExtra("LATITUDE", mStringLatitude);
	        						//	mIntent.putExtra("LONGITUDE", mStringLongitude);
	        						//	mIntent.putExtra("DAYTIME", mStringDayTime2);
	        						//
	        						//	sendBroadcast(mIntent);
	        						//}
	        						/* 2010.11.13 SANO DEL END */
	        						// カウンター初期化
	        						mTickCount = 0;
	        					}
	        				}
	        			});
	        		}
	        	}, 1000, 100
	        );
        }
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);

		// GPS開始
    	mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    	if(mLocationManager != null)
    	{
    		/*
    		Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

    		if(location != null)
    		{
    			mStringLatitude = (Double.toString(location.getLatitude()));	// 前回起動時、最後に取得した緯度
    			mStringLongitude = (Double.toString(location.getLongitude()));	// 前回起動時、最後に取得した経度
    		}
			*/
    		//mStringLatitude = "計測中";
    		//mStringLongitude = "計測中";

	    	mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, // プロバイダ
	    											0, // 通知のための最小時間間隔
	    											0, // 通知のための最小距離間隔
	    											this); // 位置情報リスナー
    	}
		getState();
		//saveState();
		sendLog();
	}

	@Override
	public void onDestroy() {

		if(mLocationManager != null)
		{
			mLocationManager.removeUpdates(this);	// GPS終了
		}

		if(mTimer != null)
		{
			mTimer.cancel();
		}
        super.onDestroy();

	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

    // 状態取得
    public void getState()
    {
    	mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE));
        mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);

        if(mWifiManager != null)
        {
        	mWifiInfo = mWifiManager.getConnectionInfo();
        }

    	mCalendar = Calendar.getInstance();

    	mConManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

    	if(mConManager != null)
    	{
    		mNetInfo = mConManager.getActiveNetworkInfo();
    	}


    	if(mNetInfo != null)
	    {
	    	// Wifiなら
	    	if(mNetInfo.getType() == ConnectivityManager.TYPE_WIFI)
	    	{
	    		// 回線種別
	    		mStringLineType = "WiFi";

	    		if(mTelephonyManager != null)
	    		{
	    			// キャリア名
	    			mStringCareerName = mTelephonyManager.getNetworkOperatorName();
	    		}
	    	}
	    	// 電話回線なら
	    	else if(mNetInfo.getType() == ConnectivityManager.TYPE_MOBILE)
	        {
	    		if(mTelephonyManager != null)
	    		{
	        		// 回線種別
	        		mStringLineType = "3G";

	        		// キャリア名
	        		mStringCareerName = mTelephonyManager.getNetworkOperatorName();
	    		}
	        }
	    	else
	    	{
	    		// その他WiMaxなど
	    		mStringLineType = "Other";

	    		// キャリア名
	    		mStringCareerName = "";
	    	}
	    }

    	if(mWifiInfo != null)
    	{
	    	mStringThroughput = Integer.toString(mWifiInfo.getLinkSpeed());
	    	mStringElectricFieldStrength = Integer.toString(mWifiInfo.getRssi());
	    	mStringBssid = mWifiInfo.getBSSID();
	    	mStringMacAddress = mWifiInfo.getMacAddress();
	    	mStringSsid = mWifiInfo.getSSID();
    	}

    	if(mCalendar != null)
    	{
	    	mStringDayTime = (
	    			/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.YEAR)) + "/" +
	    			/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.MONTH)) + "/" +
	    			/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.DAY_OF_MONTH)) + " " +
	    			/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.HOUR_OF_DAY)) + ":" +
	    			/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.MINUTE)) + ":" +
	    			/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.SECOND)) + ":" +
	    			/*Integer.toString(*/String.format("%03d",mCalendar.get(Calendar.MILLISECOND))
			    	);

	    	mStringDayTime2 = (
			    	/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.YEAR)) + "/" +
			    	/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.MONTH)) + "/" +
			    	/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.DAY_OF_MONTH)) + " " +
			    	/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.HOUR_OF_DAY)) + ":" +
			    	/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.MINUTE)) + ":" +
			    	/*Integer.toString(*/String.format("%02d",mCalendar.get(Calendar.SECOND))
			    	);
    	}
    	mStringModel = Build.MODEL;

    }

    public void saveState()
    {
    	try {
    		if(mFile != null)
    		{
    			mFos = new FileOutputStream(mFile, true);
    		}
    		if(mFos != null)
    		{
    			OutputStreamWriter osw = new OutputStreamWriter(mFos, "UTF-8");
    			if(osw != null)
    			{
		    		BufferedWriter bw = new BufferedWriter(osw);
		    		if(bw != null)
		    		{
			    		// ファイルへ書き込む文字列の生成
			    		String str = mStringDayTime + mStringLineType + "\n" +					// 回線種別
			    					 mStringDayTime + mStringThroughput + "\n" +				// スループット
			    					 mStringDayTime + mStringElectricFieldStrength + "\n" +		// 電界強度
			    					 mStringDayTime + mStringLatitude + "\n" +					// 緯度
			    					 mStringDayTime + mStringLongitude + "\n" +					// 経度
			    					 mStringDayTime + mStringBssid + "\n" +						// BSSID
			    					 mStringDayTime + mStringMacAddress + "\n" +				// MacAddress
			    					 mStringDayTime + mStringModel + "\n" +						// 端末種別
			    					 mStringDayTime + mStringSsid + "\n" +						// SSID(利用ISP？)
			    					 mStringDayTime + mStringCareerName + "\n";
			    		// バッファへ書き込み
			    		bw.write(str);
			    		// ファイルへ書き込み
			    		bw.flush();
			    		// ファイルクローズ
			    		bw.close();
		    		}
    			}
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }

    /**
     * サーバへログを送信
     */
    private void sendLog() {

    	HttpClient hc = new DefaultHttpClient();

    	// ログ保存先URL
    	String url = "http://gae-for-android.appspot.com/wifi/upload";
    	HttpPost post = new HttpPost(url);

    	// パラメータを設定
    	List<NameValuePair> params = new ArrayList<NameValuePair>();
    	params.add(new BasicNameValuePair("time", mStringDayTime));
    	params.add(new BasicNameValuePair("lineType", mStringLineType));
    	params.add(new BasicNameValuePair("throughput", mStringThroughput));
    	params.add(new BasicNameValuePair("strength", mStringElectricFieldStrength));
    	params.add(new BasicNameValuePair("latitude", mStringLatitude));
    	params.add(new BasicNameValuePair("longitude", mStringLongitude));
    	params.add(new BasicNameValuePair("bssId", mStringBssid));
    	params.add(new BasicNameValuePair("mcAddr", mStringMacAddress));
    	params.add(new BasicNameValuePair("model", mStringModel));
    	params.add(new BasicNameValuePair("ssId", mStringSsid));

    	try {
    		post.setEntity(new UrlEncodedFormEntity(params));

    		HttpResponse res = hc.execute(post);

    		int status = res.getStatusLine().getStatusCode();
    		if (!(status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED)) {
    			throw new RuntimeException("Request timeout");
    		}
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }

	@Override
	public void onLocationChanged(Location location) {
		// TODO 自動生成されたメソッド・スタブ

		if(location != null)
		{
			mStringLatitude = (Double.toString(location.getLatitude()));	// 緯度
			mStringLongitude = (Double.toString(location.getLongitude()));	// 経度
		}


	}

	@Override
	public void onProviderDisabled(String s) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void onProviderEnabled(String s) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void onStatusChanged(String s, int i, Bundle bundle) {
		// TODO 自動生成されたメソッド・スタブ

	}

}
